#ifndef __VFS_H
#define __VFS_H

#define FS_FILE        0x01
#define FS_DIRECTORY   0x02
#define FS_CHARDEVICE  0x03
#define FS_BLOCKDEVICE 0x04
#define FS_PIPE        0x05
#define FS_SYMLINK     0x06
#define FS_MOUNTPOINT  0x08 // Is the file an active mountpoint?

struct fs_node;//foreward delcare, will be more later in code

struct dirent // One of these is returned by the readdir call, according to POSIX.
{
  u8int name[128]; // Filename.
  u32int ino;     // Inode number. Required by POSIX.
}; 

typedef s32int             (*read_type_t)   (struct fs_node*,u32int,u32int,u8int*);
typedef s32int             (*write_type_t)  (struct fs_node*,u32int,u32int,u8int*);
typedef s32int             (*open_type_t)   (struct fs_node*);
typedef s32int             (*close_type_t)  (struct fs_node*);
typedef s32int             (*scan_type_t)  (struct fs_node*);

typedef struct fs_node
{
   u8int name[128];					// The filename.
	u32int length;				// Size of the file, in bytes.
	u32int position;

   u32int mask;				// The permissions mask.
   //u32int uid;				// The owning user.
   //u32int gid;				// The owning group.
   u32int flags;				// Includes the node type. See #defines above.
   u32int inode;				// Provides a way for a filesystem to identify files.
   
	//pointers to standard file routines. Should be setup by the file system drivers.
   read_type_t read;
   write_type_t write;
   open_type_t open;
   close_type_t close;
	scan_type_t scan;
   
	u32int dvr_num;	      // for use by the file system drivers
	u32int *dvr_ptr;			// for use by the file system drivers

	struct fs_node *ptr; 			// Used by mountpoints and symlinks.
	struct fs_node *parent;
	struct fs_node *first_child;	//the first child node (for directories only)
	struct fs_node *next_sibling;	//the next sibling node. (could be a file or a directory)

} fs_node_t;

// Standard read/write/open/close functions. Note that these are all suffixed with
// _fs to distinguish them from the read/write/open/close which deal with file descriptors
// not file nodes.

s32int scan_fs(fs_node_t* node);

s32int seek_fs(fs_node_t* node, u32int offset);

//reads 'size' bytes from 'node's32into the start of 'buffer' starting at 'offset' 
s32int read_fs(fs_node_t* node, u32int size, u8int *buffer);

//writes 'size' bytes from the start of 'buffer's32into 'node' starting at 'offset' 
s32int write_fs(fs_node_t* node, u32int size, u8int *buffer);

//creates a file handle for 'node', allowing safe reads and writes to it. 
fs_node_t* open_fs(s8int* path);

//destroys the file handle for 'node', locking reads and writes to the file.
s32int close_fs(fs_node_t* node);

//returns the n'th child node of the given directory or NULL if it doesn't exist.
struct dirent *readdir_fs(fs_node_t *node, u32int index);

//returns a node based on the given path name starting at the given node. NULL if it doesn't exist.
fs_node_t *finddir_fs(fs_node_t *node, s8int *name); 

//backtraces from the given node to the root finding the full path name of the node
s8int* fs_fill_path(fs_node_t* node, s8int* path);

void init_vfs(void);
void init_vfs_interface(void);

u32int get_valid_inode(void);
#endif
